export const formatTime = (date: Date) => {
  // const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  // const second = date.getSeconds()

  return (
    [month, day].map(formatNumber).join('/') +
    ' ' +
    [hour, minute].map(formatNumber).join(':')
  )
}

const formatNumber = (n: number) => {
  const s = n.toString()
  return s[1] ? s : '0' + s
}
const highLevel = ['×', '÷']
const lowLevel = ['+', '-']
export const getNumber = (min = 1, max = 9) => {
  return min + Math.round(Math.random() * (max - min))
}
function getAction(): string {
  const mid = Math.random()
  if (mid < 0.25) {
    return '+'
  } else if (mid < 0.5) {
    return '-'
  } else if (mid < 0.75) {
    return '×'
  } else {
    return '÷'
  }
}
export const getExam = (type: string) => {
  switch (type) {
    case '乘加乘减':
      return timesPlusMinus()
      break;
    case '除法':
      return division()
      break;
    case '乘法':
      return times()
      break;
    case '20以内加减':
      return plusMinus(20, 1)
      break;
    case '100以内加减':
      return plusMinus(100, 1)
      break;
    case '三位数加减':
      return plusMinus(999, 100)
      break;
    case '混合运算':
      return arithmetic()
      break;
    case '带余数除法':
      return divisionUpdate()
      break;
    default:
      return []
  }
}
//乘加乘减
function timesPlusMinus() {
  const num1 = getNumber(1, 9)
  const num2 = getNumber(1, 9)
  let num3 = getNumber(1, 99)
  const action2 = Math.random() > 0.5 ? '+' : '-'
  if (action2 === '+') {
    num3 = getNumber(1, 99 - num1 * num2)
  }
  const res: string[] = []
  const answer = action2 === '+' ? (num1 * num2 + num3) : (num1 * num2 - num3)
  if (answer >= 0) {
    res.push([num1, '×', num2, action2, num3].join(''), String(answer))
  } else {
    res.push([num3, action2, num1, '×', num2].join(''), String(-answer))
  }
  return res
}
// 除法
function division() {
  const num1 = getNumber(1, 9)
  const num2 = getNumber(1, 9)
  return [[num1 * num2, '÷', num2].join(''), String(num1)]
}
// 带余数除法
function divisionUpdate() {
  const num1 = getNumber(1, 9)
  const num2 = getNumber(2, 9)
  const yuShu = getNumber(1, num2 - 1)
  return [[num1 * num2 + yuShu, '÷', num2].join(''), `${num1}余${yuShu}`]
}
// 乘法
function times() {
  const num1 = getNumber(1, 9)
  const num2 = getNumber(1, 9)
  return [[num1, '×', num2].join(''), String(num1 * num2)]
}
// 加减法
function plusMinus(max: number, min: number): string[] {
  const num1 = getNumber(min, max)
  const num2 = getNumber(min, max)
  const action = Math.random() > 0.5 ? '+' : '-'
  const answer = action === '+' ? num1 + num2 : num1 - num2;
  if (Math.abs(answer) <= max) {
    if (answer >= 0) {
      return [[num1, action, num2].join(''), String(answer)]
    } else {
      return [[num2, action, num1].join(''), String(-answer)]
    }
  } else {
    return plusMinus(max, min)
  }
}
// 混合运算
function arithmetic(): string[] {
  const action1 = getAction()
  const action2 = getAction()
  const index = addBracket()
  const [num1, num2, num3] = getData(action1, action2, index)
  const mid = [num1, action1, num2, action2, num3]
  if (index > -1) {
    mid.splice(index, 0, '(')
    mid.splice(index + 4, 0, ')')
  }
  const str = mid.join('')
  const res = getResult(mid)
  return [str, String(res)]
}
// 混合运算添加括号
function addBracket() {
  const mid = Math.random()
  let index
  if (mid < 0.5) {
    index = -1
  }
  else if (mid < 0.75) {
    index = 0
  } else {
    index = 2
  }
  return index
}
// 修数以保证能除尽，乘数不大于10
function getData(action1: string, action2: string, index: number): number[] {
  if (index < 0) {
    return getDataNoBracket(action1, action2)
  } else {
    return getDataWithBracket(action1, action2, index)
  }
}
// 混合运算无括号
function getDataNoBracket(action1: string, action2: string): number[] {
  let num1 = 1, num2 = 1, num3 = 1
  if (action1 === '×') {
    num1 = getNumber(1, 9)
    num2 = getNumber(1, 9)
    switch (action2) {
      case '×':
        num3 = getNumber(1, 9)
        num2 = getNumber(1, Math.floor(9 / num1))
        break;
      case '÷':
        num3 = getNumber(1, 9);
        const [a, b] = getDividParent(num3)
        num1 = a
        num2 = b
        break;
      case '+':
        num3 = getNumber(1, 99 - num1 * num2);
        break;
      case '-':
        num3 = getNumber(1, num1 * num2);
        break;
    }
  } else if (action1 === '÷') {
    num2 = getNumber(1, 9)
    const dividRes = getNumber(1, 9)
    num1 = dividRes * num2
    switch (action2) {
      case '×':
        num3 = getNumber(1, 9)
        break;
      case '÷':
        num3 = getDivided(dividRes)
        break;
      case '+':
        num3 = getNumber(1, 99 - num1 / num2);
        break;
      case '-':
        num3 = getNumber(1, num1 / num2);
        break;
    }
  } else if (action1 === '+') {
    switch (action2) {
      case '+':
        num1 = getNumber(1, 97)
        num2 = getNumber(1, 98 - num1)
        num3 = getNumber(1, 99 - num1 - num2)
        break;
      case '-':
        num1 = getNumber(1, 98)
        num2 = getNumber(1, 99 - num1)
        num3 = getNumber(1, num1 + num2)
        break;
      case '×':
        num2 = getNumber(1, 9)
        num3 = getNumber(1, 9)
        num1 = getNumber(1, 99 - num2 * num3)
        break;
      case '÷':
        num3 = getNumber(1, 9)
        num2 = getNumber(1, 9) * num3
        num1 = getNumber(1, 99 - num2 / num3)
        break;
    }
  } else {
    switch (action2) {
      case '+':
        num2 = getNumber(1, 98)
        num1 = getNumber(num2 + 1, 99)
        num3 = getNumber(1, 99 - (num1 - num2))
        break;
      case '-':
        num3 = getNumber(1, 97)
        num2 = getNumber(1, 98 - num3)
        num1 = getNumber(num2 + num3 + 1, 99)
        break;
      case '×':
        num2 = getNumber(1, 9)
        num3 = getNumber(1, 9)
        num1 = getNumber(num2 * num3 + 1, 99)
        break;
      case '÷':
        num3 = getNumber(1, 9)
        num2 = getNumber(1, 9) * num3
        num1 = getNumber(num2 / num3 + 1, 99)
        break;
    }
  }
  return [num1, num2, num3]
}
// 混合运算有括号
function getDataWithBracket(action1: string, action2: string, index: number) {
  let num1 = 1, num2 = 1, num3 = 1, bracketRes = 1
  if (index === 0) {
    switch (action2) {
      case '×':
        num3 = getNumber(1, 9)
        bracketRes = getNumber(2, 9)
        break;
      case '÷':
        num3 = getNumber(1, 9)
        if (action1 === '÷') {
          bracketRes = getNumber(2, 9)
          const mid = []
          for (let j = 1; j <= bracketRes; j++) {
            if (bracketRes % j === 0) {
              mid.push(j)
            }
          }
          num3 = mid[getNumber(0, mid.length - 1)]
        } else {
          bracketRes = getNumber(2, 9) * num3
        }
        break;
      case '+':
        if (action1 === '÷') {
          bracketRes = getNumber(2, 9)
        } else {
          bracketRes = getNumber(1, 9) * getNumber(1, 9)
        }
        num3 = getNumber(1, 99 - bracketRes);
        break;
      case '-':
        if (action1 === '÷') {
          bracketRes = getNumber(2, 9)
        } else {
          bracketRes = getNumber(1, 9) * getNumber(1, 9)
        }
        num3 = getNumber(1, bracketRes);
        break;
    }
    const [a, b] = getBracketData(action1, bracketRes)
    num1 = a
    num2 = b
    return [num1, num2, num3]
  } else {
    switch (action1) {
      case '×':
        num1 = getNumber(1, 9)
        bracketRes = getNumber(2, 9)
        break;
      case '÷':
        bracketRes = getNumber(2, 9)
        num1 = getNumber(1, 9) * bracketRes
        break;
      case '+':
        if (action2 === '÷') {
          bracketRes = getNumber(1, 9)
        } else {
          bracketRes = getNumber(1, 9) * getNumber(1, 9)
        }
        num1 = getNumber(1, 99 - bracketRes);
        break;
      case '-':
        if (action2 === '÷') {
          bracketRes = getNumber(1, 9)
        } else {
          bracketRes = getNumber(1, 9) * getNumber(1, 9)
        }
        num1 = getNumber(bracketRes + 1, 99);
        break;
    }
    const [a, b] = getBracketData(action2, bracketRes)
    num2 = a
    num3 = b
    return [num1, num2, num3]
  }
}
// 根据结果求括号内的运算参与数
function getBracketData(action: string, res: number) {
  let num1: number = 1, num2: number = 1;
  switch (action) {
    case '+':
      num1 = getNumber(1, res - 1)
      num2 = res - num1
      break;
    case '-':
      num2 = getNumber(1, 99 - res)
      num1 = num2 + res
      break;
    case '×':
      const mid = []
      for (let i = 1; i <= res; i++) {
        if (res % i === 0 && res / i <= 9 && i <= 9) {
          mid.push(i)
        }
      }
      num1 = mid[getNumber(0, mid.length - 1)]
      num2 = res / num1
      break;
    case '÷':
      num2 = getNumber(1, 9)
      num1 = num2 * res
      break;
  }
  return [num1, num2]
}
// 已知除数，取由乘法组成的被除数
function getDividParent(num3: number) {
  let num1, num2;
  const mid = getNumber(1, 9) * num3
  const arr: number[] = []
  for (let i = 1; i <= mid; i++) {
    if (mid % i === 0 && mid / i <= 9) {
      arr.push(i)
    }
  }
  const index = getNumber(0, arr.length - 1)
  num1 = arr[index]
  num2 = mid / num1
  return [num1, num2]
}
// 已知被除数，生成随机除数
function getDivided(num: number) {
  const arr = []
  for (let i = 1; i <= num; i++) {
    if (num % i === 0) {
      arr.push(i)
    }
  }
  const index = getNumber(0, arr.length - 1)
  return arr[index]
}

// 计算表达式结果,只考虑一层括号的情况，不考虑多层括号嵌套
function getResult(arr: any[]) {
  const index = arr.indexOf('(')
  if (index > -1) {
    const [num1, action, num2] = [...arr].splice(index + 1, 3)
    const mid = getBasicResult(num1, action, num2)
    arr.splice(index, 5, mid)
    return getBasicResult(arr[0], arr[1], arr[2]);
  } else {
    if (highLevel.includes(arr[3]) && lowLevel.includes(arr[1])) {
      const mid = getBasicResult(arr[2], arr[3], arr[4])
      return getBasicResult(arr[0], arr[1], mid)
    } else {
      const mid = getBasicResult(arr[0], arr[1], arr[2])
      return getBasicResult(mid, arr[3], arr[4])
    }
  }
}
function getBasicResult(num1: number, action: string, num2: number): number {
  switch (action) {
    case '+':
      return num1 + num2
    case '-':
      return num1 - num2
    case '×':
      return num1 * num2
    default:
      return num1 / num2
  }
}
